using IQIGame.Onigao.GameAOT;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using UnityEngine.Timeline;

namespace IQIGame.Onigao.GamePlay.Editors
{
    public abstract class GenArtPrefabBase
    {
        public abstract ArtModeGenType genPrefabType { get; }
        protected string entityName { get; set; }
        protected string basePath { get; set; }
        protected abstract string outputBasePath { get; }
        protected abstract int prefabLayer { get; }

        public EntityGenConfigAsset genEntityConfig { get; protected set; }

        protected virtual string defaultGenConfigPath => "Assets/EditorConfig/ArtToolConfig/EntityGen/Common/Entity_LevelEntity.asset";
        protected virtual string entityGenConfigPath => $"Assets/EditorConfig/ArtToolConfig/EntityGen/{entityName}.asset";
        protected readonly List<EntityGenConfigAsset.BindRootTrans> defaultBindRoot = new List<EntityGenConfigAsset.BindRootTrans>
        {
            new EntityGenConfigAsset.BindRootTrans { rootName = "Top" },
            new EntityGenConfigAsset.BindRootTrans { rootName = "Middle" },
        };

        public bool GenInitial(string path, string entityName)
        {
            this.basePath = path;
            this.entityName = entityName;
            this.genEntityConfig = AssetDatabase.LoadAssetAtPath<EntityGenConfigAsset>(entityGenConfigPath);
            if (this.genEntityConfig == null)
            {
                this.genEntityConfig = AssetDatabase.LoadAssetAtPath<EntityGenConfigAsset>(this.defaultGenConfigPath);
            }
            return true;
        }

        /// <summary>
        /// 生成预设
        /// </summary>
        /// <param name="withAnimator">是否同时导出动画Animator</param>
        /// <param name="forceReplaceOld">是否强制替换已存在的预设而不询问</param>
        public abstract void GenArtPrefab(bool withAnimator, bool forceReplaceOld);

        public abstract string GetArtModeResPath();

        public virtual string GetOutputPrefabPath(string characterName, string prefabName)
        {
            return $"Assets/{this.outputBasePath}/{entityName}/{prefabName}.prefab";
        }

        protected GameObject GenPrefabInternal(string characterName, string prefabName, GameObject modelFbxObj, string animationCtrlPath, bool withAnim = true)
        {
            // 动画状态机
            AnimatorController animatorController = null;
            if (withAnim)
            {
                animatorController = AssetDatabase.LoadAssetAtPath<AnimatorController>(animationCtrlPath);
                if (animatorController == null)
                {
                    Debug.LogError($"动画文件:{animationCtrlPath}，不存在，生成Prefab失败! 请检查是否在DormDispostionAnimAsset设置并生成过{characterName}的性格");
                    return null;
                }
            }
            //生成GameObject
            GameObject rootObj = new GameObject(prefabName);
            rootObj.transform.position = Vector3.zero;
            rootObj.transform.localScale = Vector3.one;
            rootObj.transform.rotation = Quaternion.identity;
            var modelObj = PrefabUtility.InstantiatePrefab(modelFbxObj) as GameObject;
            //modelObj.name = characterName;
            modelObj.name = "model";
            modelObj.transform.SetParent(rootObj.transform);
            //设置Character层级
            rootObj.transform.SetLayer(prefabLayer);
            Avatar avatar = null;
            //删除原模型上的Animator
            if (withAnim)
            {
                var modelAni = modelObj.GetComponent<Animator>();
                if (modelAni != null)
                {
                    avatar = modelAni.avatar;
                    UnityEngine.Object.DestroyImmediate(modelAni);
                }
            }


            //SkinMesh
            var skinRenderArray = rootObj.GetComponentsInChildren<SkinnedMeshRenderer>();
            var renderArray = rootObj.GetComponentsInChildren<Renderer>();
            List<Renderer> extraCharacterRenderer = new List<Renderer>();
            //关闭阴影
            if (renderArray != null && renderArray.Length > 0)
            {
                foreach (var render in renderArray)
                {
                    //render.shadowCastingMode = isHeroDorm ? UnityEngine.Rendering.ShadowCastingMode.On : UnityEngine.Rendering.ShadowCastingMode.Off;
                    //render.receiveShadows = false;
                    //if (!(render is SkinnedMeshRenderer) && render.sharedMaterials.Where(x => x.shader.name.StartsWith(RenderConsts.CharacterShaderPrefix)).Any())
                    //{
                    //    extraCharacterRenderer.Add(render);
                    //}
                }
            }
            //添加BlendShape清理组件
            bool hasBlendShape = false;
            if (skinRenderArray != null && skinRenderArray.Length > 0)
            {
                foreach (var skinRender in skinRenderArray)
                {
                    //蒙皮网格Transfrom归零
                    skinRender.transform.localPosition = Vector3.zero;
                    skinRender.transform.localRotation = Quaternion.identity;
                    skinRender.transform.localScale = Vector3.one;

                    if (skinRender != null && skinRender.sharedMesh != null && skinRender.sharedMesh.blendShapeCount > 0)
                    {
                        hasBlendShape = true;
                        break;
                    }
                }
            }
            _ = hasBlendShape;

            //添加角色专有组件
            //var charUnit = rootObj.AddComponent<CharacterUnit>();
            //charUnit.hasBlendShape = hasBlendShape;
            //charUnit.smrArray = skinRenderArray;
            //charUnit.extraRendererArray = extraCharacterRenderer.ToArray();

            //添加动画组件
            if (!string.IsNullOrEmpty(animationCtrlPath) && withAnim)
            {
                var characterAnimator = modelObj.AddComponent<Animator>();
                characterAnimator.avatar = avatar;
                characterAnimator.runtimeAnimatorController = animatorController;
            }

            // 添加唯一实体驱动组件，处理MonoBahaviour相关，不需要再给prefab添加其他MonoBehaviour了，减少性能消耗
            var entityDriver = rootObj.AddComponent<EntityDriver>();
            entityDriver.renderers = renderArray;
            entityDriver.enabled = true;

            modelObj.AddComponent<EntityAnimEventRecevier>();

            //根据配置处理
            if (!ProcessGenEntityConfig(rootObj, modelObj, entityDriver))
            {
                Debug.LogError($"处理实体生成配置错误，请查看控制台信息");
                return null;
            }

            //额外处理
            GenPrefabExtra(rootObj, modelObj);

            return rootObj;
        }

        protected virtual bool ProcessGenEntityConfig(GameObject rootObj, GameObject modelObj, EntityDriver entityDriver)
        {
            if (this.genEntityConfig == null)
            {
                return true;
            }
            Debug.Log("[GenArtPrefabBase|ProcessGenEntityConfig] start process:" + this.entityName);


            List<GameObject> bindList = new List<GameObject>();

            // 处理特效绑定
            foreach (var e in this.genEntityConfig.effectBinds)
            {
                if (e.gameObject == null)
                {
                    Debug.LogError("[生成错误] 特效绑定-特效对象为空");
                    return false;
                }
                if (((int)e.genType & (1 << (int)this.genPrefabType)) <= 0)
                {
                    continue;
                }

                var effectObj = PrefabUtility.InstantiatePrefab(e.gameObject) as GameObject;
                var rEffectCollider = effectObj.GetComponentsInChildren<Collider>();
                if (rEffectCollider?.Length > 0)
                {
                    for (int i = 0; i < rEffectCollider.Length; i++)
                    {
                        GameObject.DestroyImmediate(rEffectCollider[i]);
                    }
                }
                if (string.IsNullOrEmpty(e.bindPath))
                {
                    effectObj.transform.SetParent(modelObj.transform);
                }
                else
                {
                    var bindParent = modelObj.transform.Find(e.bindPath);
                    if (bindParent == null)
                    {
                        effectObj.transform.SetParent(modelObj.transform);
                        Debug.LogError("[生成错误] 特效绑定-根据绑定路径找不到节点");
                        return false;
                    }
                    effectObj.transform.SetParent(bindParent.transform);
                }
                effectObj.transform.localPosition = e.localPosition;
                effectObj.transform.localRotation = Quaternion.identity;
                effectObj.transform.localScale = Vector3.one;
                effectObj.SetActive(e.defaultActive);
                if (e.holdRotation)
                {
                    var rHold = effectObj.AddComponent<TransformHold>();
                    rHold.holdRotation = true;
                }
                bindList.Add(effectObj);
            }

            // 处理特殊绑定
            foreach (var e in genEntityConfig.objectProcesses)
            {
                if (string.IsNullOrEmpty(e.path))
                {
                    bindList.Add(null);
                    continue;
                }

                var bindParent = modelObj.transform.Find(e.path);
                if (bindParent == null)
                {
                    Debug.LogError("[生成错误] GameObject绑定-根据绑定路径找不到节点");
                    return false;
                }
                bindParent.gameObject.SetActive(e.defaultActive);
                bindList.Add(bindParent.gameObject);
            }
            entityDriver.objectBinding = bindList.ToArray();

            foreach (EntityGenConfigAsset.BindingCompData data in genEntityConfig.entityComponentConfigs)
            {
                System.Type comType = EntityGenBindingComTypeBook.SearchType(data.type);
                var comp = rootObj.AddComponent(comType);
                (comp as ICompnentParams)?.SetParams(data.parmas);
            }

            float scale = genEntityConfig.modelScale;
            if (scale > 0)
            {
                modelObj.transform.localScale = new Vector3(scale, scale, scale);
            }

            return true;
        }

        protected virtual void GenPrefabExtra(GameObject rootObj, GameObject modelObj)
        {
        }

        /// <summary>
        /// 生成动作视效播放套件
        /// </summary>
        /// <param name="rootObj"></param>
        protected void GenAnimatorVFXPlayKit(GameObject rootObj)
        {
            //如果动画里配置了VFX，需要绑定播放组件
            bool needVFXPlayer = false;
            foreach (var v in genEntityConfig.customVFXStates)
            {
                if (!string.IsNullOrEmpty(v.stateName) && !string.IsNullOrEmpty(v.vfxGroup))
                {
                    needVFXPlayer = true;
                    break;
                }
            }
            if (!needVFXPlayer)
            {
                return;
            }
            var entityDriver = rootObj.AddComponent<EntityDriver>();
            if (entityDriver == null)
            {
                Debug.LogError("找不到EntityDriver");
                return;
            }
            entityDriver.isAnimatorVFXExisted = true;
            var behaviorFeatureComp = rootObj.GetOrAddComponent<BehaviorFeatureComp>();
            string entityTimelinePath = $"Assets/{Game.PathConstant.GetEntityVFXAssetPath(entityName)}";
            behaviorFeatureComp.defaultTimelineAsset = AssetDatabase.LoadAssetAtPath<TimelineAsset>(entityTimelinePath);
            //var playableDirector = rootObj.GetOrAddComponent<PlayableDirector>();
            //playableDirector.playOnAwake = false;
        }

        protected void GenBindRoot(GameObject rootObj, GameObject oldDestCharPrefab)
        {
            // 找一下rootObj的高度 （mesh最高最低点的Y差
            var rMeshFilters = rootObj.GetComponentsInChildren<SkinnedMeshRenderer>();
            var fMax = float.MinValue;
            var fMin = float.MaxValue;
            for (int i = 0; i < rMeshFilters.Length; i++)
            {
                var rBounds = rMeshFilters[i].bounds;
                if (rBounds.max.y > fMax)
                {
                    fMax = rBounds.max.y;
                }
                if (rBounds.min.y < fMin)
                {
                    fMin = rBounds.min.y;
                }
            }
            var fMeshHeight = fMax > fMin ? fMax - fMin : 1f;

            //Bind Root Transform
            //没有配置时走默认挂点
            var bindTrans = genEntityConfig != null ? genEntityConfig.bindRootTransList : defaultBindRoot;
            if (bindTrans != null && bindTrans.Count > 0)
            {
                for (int i = 0; i < bindTrans.Count; i++)
                {
                    var rName = bindTrans[i].rootName;
                    if (!string.IsNullOrEmpty(rName))
                    {
                        var bindRoot = new GameObject(rName);
                        bindRoot.transform.SetParent(rootObj.transform);
                        var rPos = new Vector3(0, fMeshHeight * bindTrans[i].defaultTransY / 100, 0);
                        if (oldDestCharPrefab)
                        {
                            var oldTrans = oldDestCharPrefab.transform.Find(rName);
                            if (oldTrans)
                            {
                                rPos = oldTrans.localPosition;
                            }
                        }
                        bindRoot.transform.localPosition = rPos;
                        bindRoot.transform.localScale = Vector3.one;
                        bindRoot.transform.rotation = Quaternion.identity;
                        bindRoot.layer = rootObj.layer;
                    }
                }
            }
        }

        protected void KeepOldCollider(GameObject rootObj, GameObject oldDestCharPrefab)
        {
            if (oldDestCharPrefab == null)
            {
                return;
            }
            Collider[] colliders = oldDestCharPrefab.GetComponents<Collider>();
            int validNum = 0;
            foreach (var collider in colliders)
            {
                if (!collider.isTrigger)
                {
                    if (collider is CapsuleCollider)
                    {
                        CopyCapsuleColliderTo(collider as CapsuleCollider, rootObj);
                        validNum++;
                    }
                    else if ((collider is BoxCollider))
                    {
                        CopyBoxColliderTo(collider as BoxCollider, rootObj);
                        validNum++;
                    }
                }
                if (validNum >= 8) //避免策划过度配置，需要使用过多的Collider时，建议使用MeshCollider
                {
                    break;
                }
            }
        }

        private static void CopyBoxColliderTo(BoxCollider collider, GameObject gameObject)
        {
            BoxCollider copy = gameObject.AddComponent<BoxCollider>();
            copy.size = collider.size;
            copy.center = collider.center;
        }

        private static void CopyCapsuleColliderTo(CapsuleCollider collider, GameObject gameObject)
        {
            CapsuleCollider copy = gameObject.AddComponent<CapsuleCollider>();
            copy.center = collider.center;
            copy.radius = collider.radius;
            copy.height = collider.height;
            copy.direction = collider.direction;
        }
    }
}